#/usr/bin/python
# -*- encoding=UTF-8 -*-

"""class for Tester

Class:
    Tester

Author:
    Limbo
"""

import os
import re
import time

import linuxlib


class Tester(linuxlib.BaseLinux):
    def __init__(self, **args):
        self.ets = args.pop('ets')
        linuxlib.BaseLinux.__init__(self, **args)

        self.wireshark_checked = False
        self.ets_checked = False
        self.set_root_password("ruutti")
        self.pcap_dir = "/tmp/log/wireshark"

    def create_localpath(self, path):
        if path and not os.path.isdir(path):
            os.makedirs(path)
            self.log('info', "Create local path " + path)
            return True
        else:
            return False

    def get_casename(self, logpath):
        foldername = os.path.basename(logpath)
        timestamp = re.findall(r"\d{8}_\d{6}", foldername)
        if not timestamp:
            return foldername
        splits = foldername.split(timestamp[0])
        if len(splits) >0 and splits[1]:
            head = splits[1][1:]
        else:
            head = splits[0][:-1]
        return "%s_%s" % (head, timestamp[0])

    def check_peu(self, revert=True):
        if not (self.connected or self.connect()):
            return False
        self.log("notice", "Checking peu server mount ", set_index='check_peu')
        kwargs = dict(head='', end='', index='check_peu', unset_index='check_peu')
        if self.check_peu_mount():
            self.log('notice', "successful", tag='g', **kwargs)
            return True
        else:
            self.log('notice', "failed", tag='r', **kwargs)
            self.log('error', "check peu server mount failed.", record=False)
            return False

    def check_peu_mount(self, retry=True):
        self.send("mount | grep /data/rnctester")
        if not self.stdout:
            if retry:
                self.sudo("mount -t nfs 10.56.16.7:/data/rnctester /data/rnctester")
                self.log('info', "Auto mount peu from 10.56.16.7")
                time.sleep(1.0)
                return self.check_peu_mount(False)
            else:
                return False
        else:
            return True

    def check_ets(self, force=False):
        if self.connected and self.ets_checked and not force:
            return True

        if not (self.connected or self.connect()):
            self.log('notice', "connecting tester err")
            return False

        if force or not self.ets_checked:
            if self.check_peu():
                self.log('notice', "Checking tester ets", end=' ')
                self.send("ls %s/test.sh" % self.ets)
                if self.stderr:
                    self.ets_checked = False
                    self.log('notice', "failed", head='', tag='r')
                    self.log('error', "Checking ets failed.", record=False)
                else:
                    self.ets_checked = True
                    self.log('notice', "successful", head='', tag='g')
            else:
                self.ets_checked = False
        return self.ets_checked

    def check_wireshark(self, force=False):
        if self.connected and self.wireshark_checked and not force:
            return True
        
        if not (self.connected or self.connect()):
            self.notice("connecting tester err")
            return False

        if force or not self.wireshark_checked:
            self.log('notice', "Checking wireshark", end=' ')
            export_cmd = "export PATH=$PATH:/usr/local/sbin:/usr/sbin:/sbin;"
            self.send("%s which dumpcap" % export_cmd)
            if self.stderr:
                self.log('notice', "failed", head='', tag='r')
                self.log('error', "Checking wireshark failed.", record=False)
                self.wireshark_checked = False
            else:
                self.log('notice', "successful", head='', tag='g')
                self.wireshark_checked = True
                dumpcap = self.stdout.splitlines()[0]
                self.send("ls -l %s" % dumpcap)
                if "-rws" not in self.stdout:
                    self.sudo("chmod +s %s" % dumpcap)
        return self.wireshark_checked

    def restart(self):
        self.log('info', "Reboot %s tester" % self.name, end=' ')
        if self.connected:
            self.sudo("reboot")
            self.log('notice', "successful", head='', tag='g')
            self.disconnect()
        else:
            self.log('notice', "failed", head='', tag='r')
            self.log('warn', "Tester not connected")

    def tad_stop(self):
        self.send("ps -ef | grep 'client/WTD'")
        if self.stdout:
            prog = re.compile(r"Dcatalina.home=(/data/[^ ]+?/client/WTD)")
            tad_home = prog.findall(self.stdout)
            if tad_home:
                self.chdir("%s/bin" % tad_home[0])
                self.sudo("./shutdown.sh", cd=True)
                self.log('info', "TAD shutdown at %s." % tad_home[0])
                return True
        return False
    
    def tad_start(self):
        tad_bin = "%s/../client/WTD/bin" % self.ets
        self.chdir(tad_bin)
        self.sudo("./startup.sh", cd=True)
        self.log('info', "TAD startup at %s." % tad_bin)
        return True

    def tad(self, cmd):
        if not self.check_ets():
            return False
        if cmd == "start":
            if self.tad_stop():
                time.sleep(3.0)
            return self.tad_start()
        elif cmd == "shutdown":
            return self.tad_stop()
        else:
            self.log('warn', "tad control command(%s) error." % cmd)
            return False

    def catch_wireshark(self):
        if not self.check_wireshark():
            return False

        self.kill_task("dumpcap", signal=9, sleep=1.5)
        cmd = "mkdir -pv {0}; rm -f {0}/*".format(self.pcap_dir)
        self.send(cmd, False)
        self.log('notice', "finding network ", set_index='find_eth')
        cmd = r"/sbin/ip addr | grep '10.30.30.10' | grep -o 'eth[0-9]'"
        self.send(cmd)
        if not self.stdout:
            self.log('warn', "no network found for wireshark.")
            return False
        else:
            eth = self.stdout
            self.log('notice', eth, head='', end='', index='find_eth', unset_index='find_eth')
        log_name = time.strftime('%Y%m%d_%H%M%S.pcap', time.localtime())
        
        export_cmd = "export PATH=$PATH:/usr/local/sbin:/usr/sbin:/sbin;"
        self.send("%s which tshark" % export_cmd)
        if self.stderr:
            self.log('error', "cannot find tshark.")
            return False
        tshark = self.stdout.splitlines()[0]
        self.log('info', "start catch wireshark to " + log_name, end=' ')
        cmd = "{0} -i {1} -w {2}/{3} 2>{2}/stderr.txt &".format(tshark, eth, self.pcap_dir, log_name)
        #cmd = "tshark -i %s -w %s/%s >stdout.txt 2>stderr.txt &" % \
        #      (self.stdout, self.pcap_dir, log_name)
        self.send(cmd, timeout=0.5)
        self.chdir(self.pcap_dir)
        self.send('echo "%s" >> task_wireshark' % log_name, cd=True)
        self.log('notice', 'done', head='')
        return True

    def catch_wireshark_stop(self):
        if not self.check_wireshark():
            return False

        self.log('info', "stop catch wireshark", end=' ')
        self.kill_task("dumpcap", sleep=1.5) and \
            self.kill_task("dumpcap", signal=9, sleep=1.0)

        self.chdir(self.pcap_dir)
        cmd = "if [ -f {0} ]; then cat {0}; rm {0}; fi".format("task_wireshark")
        self.send(cmd, cd=True)
        if self.stdout:
            logs = []
            for line in self.stdout.splitlines():
                logs.append(line)
            self.send("ls -1 *pcap", cd=True)
            for line in self.stdout.splitlines():
                if line not in logs:
                    self.send("rm -f %s" % line, cd=True)
            self.log('notice', 'done', head='')
            return True
        else:
            self.log('notice', 'failed', head='', tag='r')
            return False

    def collect_wireshark(self, logpath):
        if not self.check_wireshark():
            return False

        self.send(r"ls -1 %s/*pcap" % self.pcap_dir)
        if not self.stdout:
            self.log('warn', "no wireshark log catched.")
            return False

        self.create_localpath(logpath)
        for logname in self.stdout.splitlines():
            local_file = "%s\\%s" % (logpath, os.path.basename(logname))
            self.get(logname, local_file, "wireshark log", True)
            self.send("rm -f %s" % logname)
        return True

    def collect_ets(self, logpath):
        if not self.check_ets():
            return False

        log_dir = self.ets + "/log"
        self.chdir(log_dir)
        cmd = "ls log.txt; ls trace.txt"
        self.send(cmd, cd=True)
        if self.stderr:
            self.log('warn', "no tester logs found.")
            return False
        self.create_localpath(logpath)

        #log_name = time.strftime('tester_log_%Y%m%d_%H%M%S.zip', time.localtime())

        log_name = "%s_tester.zip" % self.get_casename(logpath)
        self.log('notice', "start getting tester logs.")

        # zip tester log
        self.send("zip %s log.txt trace.txt" % (log_name), cd=True)

        remotefile = "%s/%s" % (log_dir, log_name)
        localfile = "%s\\%s" % (logpath, log_name)
        #self.notice("getting tester log,", end=' ')
        self.get(remotefile, localfile, "tester log", True)
        self.send("rm %s" % remotefile)

        # zip peu log
        #self.notice("peu log,", False, end=' ')
        peu_log = "peu_log.txt"
        cmd = "cp /data/PeuLOG/log {0}; gzip {0}".format(peu_log)
        self.send(cmd, cd=True)

        # getting peu log
        remotefile = "%s/%s.gz" % (log_dir, peu_log)
        localfile = "%s\\%s.gz" % (logpath, peu_log)
        self.get(remotefile, localfile, "peu log", True)
        self.send("rm %s" % remotefile)

        #getting parameters.conf
        #self.notice("parameters.", False)
        remotefile = self.ets + "/config/parameters.conf"
        localfile = logpath + "\\parameters.conf"
        self.get(remotefile, localfile, "parameters", True)
        return True
